package com.iplatform.auth.config;

import com.iplatform.auth.exception.RestAccessDeniedHandler;
import com.iplatform.auth.exception.RestAuthenticationEntryPoint;
import com.iplatform.commons.PermitAllUrl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * spring security配置
 *
 * @author LiLing
 *
 */
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Value("${spring.security.login.success-forward-url}")
	private String successForwardUrl;

	@Value("${spring.security.login.default-success-url}")
	private String defaultSuccessUrl;

	@Autowired
	public UserDetailsService userDetailsService;
	@Autowired
	private PasswordEncoder passwordEncoder;

	/**
	 * 全局用户信息<br>
	 * 方法上的注解@Autowired的意思是，方法的参数的值是从spring容器中获取的<br>
	 * 即参数AuthenticationManagerBuilder是spring中的一个Bean
	 *
	 * @param auth 认证管理
	 * @throws Exception 用户认证异常信息
	 */
	@Autowired
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
	}

	/**
	 * 认证管理
	 *
	 * @return 认证管理对象
	 * @throws Exception
	 *             认证异常信息
	 */
	@Bean
	@Override
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}

	/**
	 * http安全配置
	 *
	 * @param http
	 *            http安全对象
	 * @throws Exception
	 *             http安全异常信息
	 */
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		configAccessDenied(http);
		// 不需要登录就可以访问的路径(比如:注册登录等)
		String[] includeUrls = new String[] { "/login","/oauth/token","/webjars/**","/swagger-resources/**", "/manager/out", "/css/**", "/js/**", "/images/**",
				"/core/**"};
//		http.authorizeRequests()
//				.antMatchers(HttpMethod.OPTIONS, PermitAllUrl.permitAllUrl())
//				.permitAll() // 放开权限的url
//				.anyRequest().authenticated().and()
//				.httpBasic().and().csrf().disable();

		http.authorizeRequests().antMatchers(includeUrls).permitAll()
				// 其他的访问均需验证权限
				.anyRequest().authenticated().and().formLogin()
				// 指定登录页
				// 要写在handler前面。看源码他会new覆盖掉,该方法不能与successhandler同时使用
				.loginPage("/login").permitAll().loginProcessingUrl("/login")
//				.successForwardUrl(successForwardUrl)
//				.defaultSuccessUrl(defaultSuccessUrl, true)
				// 登录成功后到index
				// 退出登录后的页面
				.permitAll().and().headers().frameOptions().disable().and().logout().logoutSuccessUrl("/login")
				.permitAll().and().csrf().disable();
	}
	/**
	 * @Author: MrRed
	 * @createDate: 2020-04
	 * @updateDate: 2020-04
	 * @Description: 配置自定义AccessDenied处理
	 **/
	private void configAccessDenied(HttpSecurity http) throws Exception {
		http.exceptionHandling()
				.authenticationEntryPoint(new RestAuthenticationEntryPoint())
				.accessDeniedHandler(new RestAccessDeniedHandler());
	}
}